home *** CD-ROM | disk | FTP | other *** search
- /*
- * localam.c --
- * POSTGRES heap access method "fast" code for temp or "retrieve into"
- * relations. NOTE: Since these relations are not visible to anyone but
- * the backend that is generating them, this code completely ignores the
- * multi-user buffer pool and utilities, and is optimized for fast appends.
- *
- * ! DO NOT USE THIS CODE FOR ANYTHING BUT TEMP OR "RETRIEVE INTO" RELATIONS !
- */
-
- #include <sys/file.h>
-
- #include "tmp/c.h"
-
- RcsId("$Header: /private/postgres/src/access/heap/RCS/localam.c,v 1.8 1992/07/13 03:09:29 hong Exp $");
-
- #include "access/heapam.h"
- #include "access/hio.h"
- #include "access/htup.h"
- #include "access/xact.h"
-
- #include "storage/block.h"
- #include "storage/buf.h"
- #include "storage/bufmgr.h"
- #include "storage/bufpage.h"
- #include "storage/itemid.h"
- #include "storage/itemptr.h"
-
- #include "utils/memutils.h"
- #include "utils/log.h"
- #include "utils/rel.h"
-
-
- typedef struct l_rellist
- {
- Relation relation;
-
- Page read_page, write_page;
- BlockNumber read_blocknum, write_blocknum;
-
- OffsetIndex offset_index;
- bool active;
- struct l_rellist *next;
- }
- LocalRelList;
-
- LocalRelList *head = NULL, *current = NULL, *tail = NULL;
- LocalRelList *GetRelListEntry(), *AddToRelList();
-
- /*
- * Public interface routines:
- */
-
- local_heap_close(relation)
-
- Relation relation;
-
- {
- LocalRelList *p = GetRelListEntry(relation);
- if (p->write_page != NULL) WriteLocalPage(p);
- DeleteRelListEntry(relation);
- }
-
- local_heap_destroy(relation)
-
- Relation relation;
-
- {
- LocalRelList *p = GetRelListEntry(relation);
- FileUnlink(p->relation->rd_fd);
- }
-
- local_heap_open(relation)
-
- Relation relation;
-
- {
- MemoryContext oldCxt;
- MemoryContext portalContext;
- Portal portal;
-
- /* ----------------
- * get the blank portal and its memory context
- * ----------------
- */
- portal = GetPortalByName(NULL);
- portalContext = (MemoryContext) PortalGetHeapMemory(portal);
-
- oldCxt = MemoryContextSwitchTo(portalContext);
- AddToRelList(relation);
- (void) MemoryContextSwitchTo(oldCxt);
- }
-
- void
- local_heap_insert(relation, tup)
- Relation relation;
- HeapTuple tup;
- {
- /* ----------------
- * increment access statistics
- * ----------------
- */
- IncrHeapAccessStat(local_insert);
- IncrHeapAccessStat(global_insert);
-
- if (!ObjectIdIsValid(tup->t_oid)) {
- tup->t_oid = newoid();
- LastOidProcessed = tup->t_oid;
- }
-
- TransactionIdStore(GetCurrentTransactionId(), &(tup->t_xmin));
- tup->t_cmin = GetCurrentCommandId();
- PointerStoreInvalidTransactionId((Pointer)&(tup->t_xmax));
- tup->t_tmin = InvalidTime;
- tup->t_tmax = InvalidTime;
-
- local_doinsert(relation, tup);
- }
-
- /*
- * These routines are called by the transaction manager. They are useful
- * in cleaning up dead temp relations and such from an AbortTransaction
- * or an elog(WARN). They do not completely solve the problem of dead
- * tmp relations, however; we have to do something about those left over from
- * a crashed backend.
- */
-
- AtAbort_LocalRels()
-
- {
- DestroyLocalRelList();
- }
-
- AtCommit_LocalRels()
-
- {
- DestroyLocalRelList();
- }
-
- /*
- * Private routines
- */
-
- LocalRelList *
- AddToRelList(relation)
-
- Relation relation;
-
- {
- if (tail == NULL)
- {
- Assert(head == NULL);
- head = (LocalRelList *) palloc(sizeof(LocalRelList));
- tail = head;
- }
- else
- {
- tail->next = (LocalRelList *) palloc(sizeof(LocalRelList));
- tail = tail->next;
- }
-
- tail->relation = relation;
- tail->read_page = tail->write_page = NULL;
- tail->read_blocknum = tail->write_blocknum = 0;
- tail->offset_index = 0;
- tail->next = NULL;
- tail->active = true;
- current = tail;
- return(tail);
- }
-
- LocalRelList *
- GetRelListEntry(relation)
-
- Relation relation;
-
- {
- LocalRelList *p;
-
- Assert(current != NULL);
- if (current->relation == relation) return(current);
-
- for (p = head; p != NULL && p->relation != relation; p = p->next);
-
- if (p == NULL) elog(WARN, "GetRelListEntry: can't find rel in list!");
- return(p);
- }
-
- /*
- * This does not do an actual list delete, but instead marks the list
- * entry as inactive and frees its page. This is done so that all the
- * temp relations can be saved and blown away at TransactionAbort time
- * if necessary by a call to DestroyLocalRelList.
- */
-
- DeleteRelListEntry(relation)
-
- Relation relation;
-
- {
- LocalRelList *p;
-
- Assert(head != NULL);
-
- for (p = head; p != NULL && p->relation != relation; p = p->next);
-
- Assert(p != NULL);
-
- p->active = false;
-
- /* don't waste excessive memory */
-
- if (p->read_page != NULL) pfree(p->read_page);
-
- if (p->write_page != NULL) pfree(p->write_page);
-
- p->read_page = p->write_page = NULL;
-
- if (current == p)
- {
- for (p = head; p->next != NULL && ! p->active; p = p->next);
-
- if (p->next == NULL) current = NULL;
- else current = p;
- }
- }
-
- /*
- * This routine is useful for AbortTransaction - it deletes the temp
- * relations in the list if they are still active. They should not ever
- * be active at TransactionCommit time, although this routine needs to
- * be called at the end of a transaction no matter what happens.
- */
-
- DestroyLocalRelList()
-
- {
- LocalRelList *p, *q;
- for (p = head; p != NULL; p = q)
- {
- if (p->active)
- {
- FileUnlink(p->relation->rd_fd);
- if (p->read_page != NULL) pfree(p->read_page);
- if (p->write_page != NULL) pfree(p->write_page);
- }
- q = p->next;
- pfree(p);
- }
- head = current = tail = NULL;
- }
-
- local_doinsert(relation, tuple)
-
- Relation relation;
- HeapTuple tuple;
-
- {
- LocalRelList *rel_info;
- Size len = LONGALIGN(tuple->t_len);
- OffsetIndex offsetIndex;
- ItemId itemId;
- HeapTuple page_tuple;
-
- rel_info = GetRelListEntry(relation);
-
- if (rel_info->write_page == NULL)
- {
- rel_info->write_page = (Page) palloc(BLCKSZ);
- PageInit(rel_info->write_page, BLCKSZ, 0);
- }
-
- if (len > PageGetFreeSpace(rel_info->write_page))
- {
- WriteLocalPage(rel_info);
- rel_info->write_blocknum++;
- bzero(rel_info->write_page, BLCKSZ);
- PageInit(rel_info->write_page, BLCKSZ, 0);
- }
-
- offsetIndex = PageAddItem((Page)rel_info->write_page, (Item)tuple,
- tuple->t_len, InvalidOffsetNumber, LP_USED) - 1;
-
- itemId = PageGetItemId((Page)rel_info->write_page, offsetIndex);
-
- page_tuple = (HeapTuple) PageGetItem(rel_info->write_page, itemId);
-
- /*
- * As this code is being used for "retrieve into" or tmp relations,
- * the RuleLock can be set to invalid as no tuple rule can exist on
- * such relations.
- */
-
- page_tuple->t_locktype = DISK_RULE_LOCK;
- ItemPointerSetInvalid(&page_tuple->t_lock.l_ltid);
-
- ItemPointerSimpleSet(&page_tuple->t_ctid,
- rel_info->write_blocknum,
- 1 + offsetIndex);
- }
-
- WriteLocalPage(rel_info)
-
- LocalRelList *rel_info;
-
- {
- unsigned long offset;
- int nbytes;
-
- offset = rel_info->write_blocknum * BLCKSZ;
-
- FileSeek(rel_info->relation->rd_fd, offset, L_SET);
-
- nbytes = FileWrite(rel_info->relation->rd_fd,
- (char *) rel_info->write_page,
- BLCKSZ);
-
- Assert(nbytes == BLCKSZ);
- }
-
- ReadLocalPage(rel_info)
-
- LocalRelList *rel_info;
-
- {
- unsigned long offset;
- int nbytes;
-
- offset = rel_info->read_blocknum * BLCKSZ;
-
- FileSeek(rel_info->relation->rd_fd, offset, L_SET);
-
- nbytes = FileRead(rel_info->relation->rd_fd,
- (char *) rel_info->read_page,
- BLCKSZ);
- return(nbytes);
- }
-